import axios from 'axios';

import type { AxiosInstance } from 'axios';

import { parseType, type MyAXiosRequestConfig } from '../types';

// let addResInterceptor = (fn1: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig, fn2: (err: any) => any) => {
//   this.instance.interceptors.request.use(fn1, fn2);
// };

class Request {
  instance: AxiosInstance; //类声明属性

  constructor(config: MyAXiosRequestConfig) {
    this.instance = axios.create(config);

    //全局请求拦截
    this.instance.interceptors.request.use(
      (config) => {
        console.log('global request success ');
        return config;
      },
      (err) => {
        console.log('global req fail~');

        return err;
      }
    );

    //全局响应拦截
    this.instance.interceptors.response.use(
      (res) => {
        console.log('global response success ');
        return res.data; //axios自己回封装一层data  处理
      },
      (err) => {
        console.log('global res fail~', err);

        return err;
      }
    );

    //用自己创建实例的拦截器
  }

  request<T = any>(config: MyAXiosRequestConfig<T>) {
    //加loading效果
    let loadingInstance: any;
    if (config.needLoading) {
      loadingInstance = ElLoading.service({ lock: true, text: 'Loading', background: 'rgba(0, 0, 0, 0.7)' });
    }

    //配置方法的拦截器 promise<any>：返回值无法具体判断 因为肯有拦截器

    return new Promise<any>((resovle, rej) => {
      //传入泛型 给res定义类型
      this.instance
        .request<any, T>(config) //T的类型就是res的类型
        .then((res) => {
          //方法独有的有拦截器执行 并且拦截掉响应数据
          if (config.interceptor?.resSuccessFn) {
            res = config.interceptor?.resSuccessFn(res);
          }

          // 是否解析对象的特定字段
          if (config.parseRessult != undefined) {
            switch (config.parseRessult) {
              case parseType.NOPARSE: //不解析
                //do noting
                break;
              case parseType.DATA: //解析data
                console.log('解析data');
                //@ts-ignore 实在解决不了
                res = res.data;
                break;
              default:
                break;
            }
          }
          resovle(res);

          loadingInstance?.close();
        })
        .catch((err) => {
          loadingInstance?.close();
          ElMessage({ type: 'error', message: `api 错误 err:${err}` });
          rej(err);
        });
    });
  }

  get<T>(config: MyAXiosRequestConfig<T>) {
    return this.request({ ...config, method: 'GET' });
  }

  post<T>(config: MyAXiosRequestConfig<T>) {
    return this.request({ ...config, method: 'POST' });
  }

  head<T>(config: MyAXiosRequestConfig<T>) {
    return this.request({ ...config, method: 'HEAD' });
  }

  patch<T>(config: MyAXiosRequestConfig<T>) {
    return this.request({ ...config, method: 'PATCH' });
  }
}
export default Request;
